﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DogDemo.Common;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace DogDemo
{
    public class ObjectManager
    {

    }

    public class ObjectCollection : ICollection<Sprite>
    {
        private List<Sprite> _internalSpriteList;
        private List<Explorer> _explorerList;
        private List<Collectable> _collectableItemList;
        private List<Mob> _mobList;
        private List<IFightable> _fighterList;

        public ObjectCollection()
        {
            this._internalSpriteList = new List<Sprite>();
            this._explorerList = new List<Explorer>();
            this._collectableItemList = new List<Collectable>();
            this._mobList = new List<Mob>();
        }

        public void Add(Sprite item)
        {
            if (!Contains(item))
            {
                this._internalSpriteList.Add(item);
            }
            else
            {
                // No fucking clue...should never happen...
            }
        }

        public void Add(Explorer explorer)
        {
            if (!Contains(explorer))
            {
                this._explorerList.Add(explorer);
            }
        }

        public void Add(Collectable collectable)
        {
            if (!Contains(collectable))
            {
                this._collectableItemList.Add(collectable);
            }
        }

        public void Add(Mob mob)
        {
            if (!Contains(mob))
            {
                this._mobList.Add(mob);
            }
        }

        public void Clear()
        {
            this._internalSpriteList.Clear();
            this._explorerList.Clear();
            this._collectableItemList.Clear();
            this._mobList.Clear();
        }

        public bool Contains(Sprite item)
        {
            bool resVal = false;

            this._internalSpriteList.ForEach(s =>
                {
                    if (s.GetHashCode() == item.GetHashCode())
                    {
                        resVal = true;
                    }
                });

            return resVal;
        }

        public void CopyTo(Sprite[] array, int arrayIndex)
        {
            for (int i = 0; i < this._internalSpriteList.Count(); i++)
            {
                array[i] = (Sprite)this._internalSpriteList[i];
            }
        }

        public int Count
        {
            get { return this._internalSpriteList.Count(); }
        }

        public bool IsReadOnly
        {
            get { return false; /* meh */ }
        }

        public bool Remove(Sprite item)
        {
            for(int i = 0; i < this._internalSpriteList.Count(); i++)
                {
                    if (item.GetHashCode() == this._internalSpriteList[i].GetHashCode())
                    {
                        this._internalSpriteList.RemoveAt(i);
                        return true;
                    }
                };
            return false;
        }

        public IEnumerator<Sprite> GetEnumerator()
        {
            return new ObjectEnumerator(this);
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }

        public void CollisionDetect(bool isUsingBox)
        {
            _explorerList.ForEach(explorer =>
            {
                _collectableItemList.ForEach(collectable => 
                {
                    if (explorer.BoundingBoxRect.Intersects(collectable.BoundingBoxRect))
                    {
                        explorer.DoCollect(collectable);
                        collectable.DoCollected();
                    }
                });

                _mobList.ForEach(mob =>
                    {
                        if (explorer.BoundingBoxRect.Intersects(mob.BoundingBoxRect))
                        {
                            // flip to battle mode
                            WorldManager.GameState = WorldManager.GameStates.Combat;
                        }
                    });
            });
        }

        public void DoDrawing(SpriteBatch spriteBatch, DogDemo.WorldManager.GameStates gameState)
        {
            switch (gameState)
            {
                case DogDemo.WorldManager.GameStates.OpenWorld:
                    _explorerList.ForEach(explorer =>
                    {
                        explorer.DoDraw(spriteBatch);
                    });
                    _collectableItemList.ForEach(collectable =>
                    {
                        collectable.DoDraw(spriteBatch);
                    });
                    _mobList.ForEach(mob =>
                    {
                        mob.DoDraw(spriteBatch);
                    });
                    break;
                case DogDemo.WorldManager.GameStates.Combat:
                    spriteBatch.GraphicsDevice.Clear(Color.Magenta);
                    break;
            }
        }

        public void DoUpdating(GameTime gameTime, DogDemo.WorldManager.GameStates gameState, ref TileMap tileMap)
        {
            switch (gameState)
            {
                case DogDemo.WorldManager.GameStates.OpenWorld:
                    CollisionDetect(true);
                    // refs not allowed in lambda expressions :/
                    foreach (Explorer explorer in _explorerList)
                    {
                        explorer.DoUpdate(gameTime, ref tileMap);
                    }
                    break;
            }
        }
    }

    class ObjectEnumerator : IEnumerator<Sprite>
    {
        private ObjectCollection _objCollection;
        private int _objIndex;
        private Sprite _objSprite;

        public ObjectEnumerator(ObjectCollection collection)
        {
            this._objCollection = collection;
            this._objIndex = -1;
            this._objSprite = default(Sprite);
        }
        public Sprite Current
        {
            get { return this._objSprite; }
        }

        public void Dispose()
        {
            
        }

        object System.Collections.IEnumerator.Current
        {
            get { return this.Current; }
        }

        public bool MoveNext()
        {
            this._objIndex++;
            if (this._objIndex >= this._objCollection.Count())
            {
                return false;
            }
            else
            {
                this._objSprite = this._objCollection.ToList()[this._objIndex];
            }

            return true;
        }

        public void Reset()
        {
            this._objIndex = -1;
        }
    }
}
